package com.aterrizar.sistema;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.aterrizar.aerolinea.Aerolinea;
import com.aterrizar.aerolinea.Lanchita;
import com.aterrizar.aerolinea.Oceanic;
import com.aterrizar.asiento.Asiento;
import com.aterrizar.exception.AsientoReservadoPorOtroException;
import com.aterrizar.exception.ReservaNoRealizadaException;
import com.aterrizar.usuario.Usuario;

public class Aterrizar {

	private static final Aterrizar INSTANCE = new Aterrizar();
	private Set<Aerolinea> aerolineas;
	private Set<Usuario> usuarios;
	private List<Asiento> asientosReservados;
	private Map<String, Integer> vuelosComprados;

	public Aterrizar() {
		aerolineas = new HashSet<Aerolinea>();
		usuarios = new HashSet<Usuario>();
		asientosReservados = new ArrayList<Asiento>();
		vuelosComprados = new HashMap<String, Integer>();
		Oceanic.getInstance().setPorcentaje(Integer.valueOf(20));
		Lanchita.getInstance().setPorcentaje(Integer.valueOf(20));
		aerolineas.add(Lanchita.getInstance());
		aerolineas.add(Oceanic.getInstance());
	}

	/**
	 * Busca asientos disponibles y los devuelve.
	 * 
	 * @param origen
	 *            Origen del vuelo
	 * @param destino
	 *            Destino del vuelo
	 * @param fecha
	 *            Fecha del vuelo
	 * @param clase
	 *            Clase del asiento
	 * @param ubicacion
	 *            Ubicacion del asiento
	 * @return Set<Asiento> con los asientos disponibles que se ajustan a la
	 *         busqueda
	 */
	public List<Asiento> buscar(Usuario usuario, String origen, String destino,
			String fechaSalida, String horaSalida, String horaLlegada) {
		List<Asiento> fAsientos = new ArrayList<Asiento>();

		for (Aerolinea aerolinea : aerolineas) {
			Set<Asiento> asientosAerolinea = aerolinea.buscar(usuario, origen,
					destino, fechaSalida, horaSalida, horaLlegada);
			fAsientos.addAll(asientosAerolinea);
		}
		return fAsientos;
	}

	/**
	 * Reserva un pasaje seleccionado
	 * 
	 * @param codigo
	 *            Codigo del asiento seleccionado
	 * @param dni
	 *            DNI de la persona que reserva el pasaje
	 * @throws ReservaNoRealizadaException
	 */
	public void reservar(String codigo, String dni, Aerolinea aerolinea) {
		try {
			aerolinea.reservar(codigo, dni);
		} catch (ReservaNoRealizadaException e) {
			throw new AsientoReservadoPorOtroException();
		}
	}

	public static Aterrizar getInstance() {
		return INSTANCE;
	}

	public void agregarAerolinea(Aerolinea aerolinea) {
		aerolineas.add(aerolinea);
	}

	public void agregarUsuario(Usuario usuario) {
		usuarios.add(usuario);
	}

	public void comprar(Asiento asiento) {
		Aerolinea aerolinea = asiento.getAerolinea();
		String codigo = asiento.getCodigo();
		String dniPasajero = asiento.getDniPasajero();
		aerolinea.comprar(codigo, dniPasajero);
		agregarVueloComprado(aerolinea, codigo);
	}

	// private void agregarVueloComprado(Aerolinea aerolinea, String codigo) {
	// Vuelo vuelo = new Vuelo(aerolinea, codigo);
	// if (vuelosComprados.containsKey(vuelo)) {
	// Integer cantidad = vuelosComprados.get(vuelo);
	// cantidad++;
	// } else {
	// vuelosComprados.put(vuelo, 1);
	// }
	// }
	//
	private void agregarVueloComprado(Aerolinea aerolinea, String codigo) {
		String[] split = codigo.split("-");
		String codigoVuelo = split[0];
		if (vuelosComprados.containsKey(codigoVuelo)) {
			Integer cantidad = vuelosComprados.get(codigoVuelo);
			cantidad++;
			vuelosComprados.put(codigoVuelo, cantidad);
		} else {
			vuelosComprados.put(codigoVuelo, 1);
		}
	}

	public List<Asiento> getAsientosReservados() {
		return asientosReservados;
	}

	public void setAsientosReservados(List<Asiento> asientosReservados) {
		this.asientosReservados = asientosReservados;
	}

	public Map<String, Integer> getVuelosComprados() {
		return vuelosComprados;
	}

	public void setVuelosComprados(Map<String, Integer> vuelosComprados) {
		this.vuelosComprados = vuelosComprados;
	}

	public List<Asiento> encontrarAsientosEnReservas(String origen,
			String destino, String fecha, String hora, String horaSalida) {
		List<Asiento> asientos = new ArrayList<Asiento>(asientosReservados);
		List<Asiento> rechazados;
		if (null != origen) {
			rechazados = new ArrayList<Asiento>();
			for (Asiento asiento : asientos) {
				if (!asiento.getOrigen().equalsIgnoreCase(origen)) {
					rechazados.add(asiento);
				}
			}
			asientos.removeAll(rechazados);
		}
		if (null != destino) {
			rechazados = new ArrayList<Asiento>();
			for (Asiento asiento : asientos) {
				if (!asiento.getDestino().equalsIgnoreCase(destino)) {
					rechazados.add(asiento);
				}
			}
			asientos.removeAll(rechazados);
		}

		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
		if (null != fecha && null != hora) {
			rechazados = new ArrayList<Asiento>();
			for (Asiento asiento : asientos) {
				Date fechaAsientoLlegada = null;
				Date fechaAsientoSalida = null;
				Date fechaAComparar = null;
				try {
					fechaAsientoLlegada = sdf.parse(asiento.getFechaLlegada()
							+ " " + asiento.getHoraLlegada());
					fechaAsientoSalida = sdf.parse(asiento.getFechaSalida()
							+ " " + asiento.getHoraSalida());
					fechaAComparar = sdf.parse(fecha + " " + hora);
				} catch (ParseException e) {
					return null;
				}
				if (!(fechaAComparar.equals(fechaAsientoSalida) || fechaAComparar
						.equals(fechaAsientoLlegada))) {
					rechazados.add(asiento);
				}
			}
			asientos.removeAll(rechazados);
		}

		return asientos;

	}

	public void removerCaducados(List<Asiento> vencidos) {
		for (Asiento asiento : vencidos) {
			asientosReservados.get(asientosReservados.indexOf(asiento))
					.traspasarReserva();
		}
	}

}
